/*
  Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; version 2 of the License.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <gmock/gmock.h>

#include <cstdlib>
#include <cstring>
#include <string.h>

#include "mysqlrouter/mysql_protocol.h"
#include "mysqlrouter/utils.h"

using std::string;
using ::testing::ContainerEq;
using ::testing::NotNull;

class HandshakeResponsePacketTest : public ::testing::Test {
protected:
  virtual void SetUp() {
  }
};

TEST_F(HandshakeResponsePacketTest, DefaultConstructor) {
  mysql_protocol::HandshakeResponsePacket p{};

  std::vector<unsigned char> exp {
      0x4d, 0x00, 0x00, 0x00, 0x8d, 0xa2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
      0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x00, 0x6d, 0x79, 0x73, 0x71, 0x6c,
      0x5f, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
      0x00,
  };

  ASSERT_THAT(p, ContainerEq(exp));
}

TEST_F(HandshakeResponsePacketTest, Constructor) {
  std::vector<unsigned char> auth_data = {0x50, 0x51, 0x50, 0x51, 0x50, 0x51};
  {
    // Setting the username; empty password
    mysql_protocol::HandshakeResponsePacket p(1, auth_data, "ROUTERTEST", "");

    std::vector<unsigned char> exp {
        0x57, 0x00, 0x00, 0x01, 0x8d, 0xa2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x52, 0x54, 0x45, 0x53, 0x54, 0x00, 0x14,
        0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
        0x71, 0x71, 0x71, 0x71, 0x00, 0x6d, 0x79, 0x73, 0x71, 0x6c, 0x5f, 0x6e, 0x61, 0x74, 0x69, 0x76,
        0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x00,
    };

    ASSERT_THAT(p, ContainerEq(exp));
  }

  {
    // Database set
    mysql_protocol::HandshakeResponsePacket p(1, auth_data, "ROUTERTEST", "", "router_db");

    std::vector<unsigned char> exp {
        0x60, 0x00, 0x00, 0x01, 0x8d, 0xa2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x52, 0x54, 0x45, 0x53, 0x54, 0x00, 0x14,
        0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
        0x71, 0x71, 0x71, 0x71, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x64, 0x62, 0x00, 0x6d, 0x79,
        0x73, 0x71, 0x6c, 0x5f, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77,
        0x6f, 0x72, 0x64, 0x00
    };

    ASSERT_THAT(p, ContainerEq(exp));
  }

  {
    // Character set
    mysql_protocol::HandshakeResponsePacket p(1, auth_data, "ROUTERTEST", "", "router_db", 80);

    std::vector<unsigned char> exp {
        0x60, 0x00, 0x00, 0x01, 0x8d, 0xa2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x52, 0x54, 0x45, 0x53, 0x54, 0x00, 0x14,
        0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
        0x71, 0x71, 0x71, 0x71, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x64, 0x62, 0x00, 0x6d, 0x79,
        0x73, 0x71, 0x6c, 0x5f, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77,
        0x6f, 0x72, 0x64, 0x00
    };

    ASSERT_THAT(p, ContainerEq(exp));
  }

  {
    // Character set
    mysql_protocol::HandshakeResponsePacket p(1, auth_data, "ROUTERTEST", "", "router_db", 8, "router_auth_plugin");

    std::vector<unsigned char> exp {
        0x5d, 0x00, 0x00, 0x01, 0x8d, 0xa2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x52, 0x54, 0x45, 0x53, 0x54, 0x00, 0x14,
        0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
        0x71, 0x71, 0x71, 0x71, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x64, 0x62, 0x00, 0x72, 0x6f,
        0x75, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
        0x00,
    };

    ASSERT_THAT(p, ContainerEq(exp));
  }
}

